#ifndef __HDVB_SECFILTER_H
#define __HDVB_SECFILTER_H
/*
    libhdvbd - Library for building sophisticated DVB applications
    Copyright (C) 2012 Tony Houghton <h@realh.co.uk>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* High-level handling of section filters */

#include <glib.h>

#include <hdvb/hdvb-receiver.h>
#include <hdvb/section.h>

G_BEGIN_DECLS

/* Recommended timeout for section filters */
#define HDVB_SECTION_FILTER_TIMEOUT 10000

typedef struct _HdvbSectionFilter HdvbSectionFilter;

/* Called when a section is received (reason == 0) or other reasons (errno).
 * If not in harvest mode each section should be freed with
 * g_slice_free(HdvbSection, ...). If reason and section are both 0 it means
 * a section which was already harvested has been received again and you
 * should test for completeness.
 * handle comes first to make it easier to use with GObject.
 */
typedef void (*HdvbSectionFilterCallback)(gpointer handle, int reason,
        HdvbSection *section, HdvbSectionFilter *sctf);

struct _HdvbSectionFilter {
    HdvbReceiver *rcv;
    GHashTable *sections;   /* Keyed by section_id.
                             * Each member is an array of sections. */
    guint8 table_id;        /* Set but not used internally */
    int pid;                /* caller may use them for reference */
    /* Consider following members "private" */
    HdvbSectionFilterCallback callback;
    gpointer cb_handle;
    int fd;
    GMutex lock;
    gboolean has_lock;
    gboolean running;
    int ref;
    gboolean xl;
    int timeout;
    gboolean include_next;
    gboolean got_repeat;
    gboolean multi_id;
};

/* If harvest is TRUE, sections are collected in the sections member and you
 * may use hdvb_section_filter_table_is_complete to test for the complete set.
 * Harvesting won't work for segmented sections and/or filters with multiple
 * table_ids etc such as EIT. If the version_number changes during harvest and
 * current_next_indicator is 1, sections with old version are deleted.
 * If include_next is TRUE, callback is called for sections where
 * current_next_indicator is 0, but they will not be harvested.
 * timeout is in milliseconds.
 * If multi_id is TRUE, sections with different section_ids are to be received,
 * each considered as a separate table.
 */
HdvbSectionFilter *
hdvb_section_filter_new_named(HdvbReceiver *rcv, const char *thread_name,
        int pid, guint8 table_id, guint8 table_id_mask,
        guint16 section_id, guint16 section_id_mask,
        int timeout,
        HdvbSectionFilterCallback callback,
        gboolean harvest, gboolean include_next, gboolean multi_id,
        gpointer handle);

inline static HdvbSectionFilter *
hdvb_section_filter_new(HdvbReceiver *rcv,
        int pid, guint8 table_id, guint8 table_id_mask,
        guint16 section_id, guint16 section_id_mask,
        int timeout,
        HdvbSectionFilterCallback callback,
        gboolean harvest, gboolean include_next, gboolean multi_id,
        gpointer handle)
{
    return hdvb_section_filter_new_named(rcv, NULL,
            pid, table_id, table_id_mask, section_id, section_id_mask,
            timeout, callback, harvest, include_next, multi_id, handle);
}

/* NB frees harvested sections */
void
hdvb_section_filter_delete(HdvbSectionFilter *sctf);

gboolean
hdvb_section_filter_table_is_complete(HdvbSectionFilter *sctf);

/* Allows filter to be stopped without destroying harvested sections */
void
hdvb_section_filter_stop(HdvbSectionFilter *sctf);

/* Lists all the harvested sections */
GList *
hdvb_section_filter_list_sections(HdvbSectionFilter *sctf);

G_END_DECLS

#endif /* __HDVB_SECFILTER_H */
